package com.shaoyu.tools.event.core;


import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author shaoyu
 * @date 2022/11/2 17:29
 */
public interface CustomSubscribeExceptionHandler<T> extends SubscriberExceptionHandler {

    CustomSubscribeExceptionHandler LOGGING_HANDLER = new LoggingHandler();

    /**
     * 获取泛型类型
     * @return 泛型T的真实类型
     */
    default Class<T> getEventClass(){
        Class<? extends CustomSubscribeExceptionHandler> clz = this.getClass();
        //获取接口类型
        Type[] genericInterfaces = clz.getGenericInterfaces();
        for (Type type : genericInterfaces) {
            //筛选出带参数的接口类型(泛型)
            if(type instanceof ParameterizedType){
                ParameterizedType parameterizedType = (ParameterizedType)type;
                //获取实际参数类型(泛型类型)
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                if(actualTypeArguments!=null && actualTypeArguments.length == 1){
                    return (Class)actualTypeArguments[0];
                }
            }
        }
        return null;
    }

    class LoggingHandler implements CustomSubscribeExceptionHandler<Object>{
        //copy from EventBus.LoggingHandler

        private LoggingHandler(){}

        @Override
        public void handleException(Throwable exception, SubscriberExceptionContext context) {
            Logger logger = logger(context);
            if (logger.isLoggable(Level.SEVERE)) {
                logger.log(Level.SEVERE, message(context), exception);
            }
        }

        private static Logger logger(SubscriberExceptionContext context) {
            String var1 = EventBus.class.getName();
            String var2 = context.getEventBus().identifier();
            return Logger.getLogger((new StringBuilder(1 + String.valueOf(var1).length() + String.valueOf(var2).length())).append(var1).append(".").append(var2).toString());
        }

        private static String message(SubscriberExceptionContext context) {
            Method method = context.getSubscriberMethod();
            String var2 = method.getName();
            String var3 = method.getParameterTypes()[0].getName();
            String var4 = String.valueOf(context.getSubscriber());
            String var5 = String.valueOf(context.getEvent());
            return (new StringBuilder(80 + String.valueOf(var2).length() + String.valueOf(var3).length() + String.valueOf(var4).length() + String.valueOf(var5).length())).append("Exception thrown by subscriber method ").append(var2).append('(').append(var3).append(')').append(" on subscriber ").append(var4).append(" when dispatching event: ").append(var5).toString();
        }
    }
}
